package com.pb.wkflow.core.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.pb.infra.oth.exception.BizException;
import com.pb.wkflow.api.exception.ApprovalException;
import com.pb.wkflow.core.camunda.bpmn.instance.*;
import com.pb.wkflow.core.service.WorkflowModelService;
import com.pb.wkflow.core.utils.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnDiagram;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnEdge;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnPlane;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnShape;
import org.camunda.bpm.model.bpmn.instance.dc.Bounds;
import org.camunda.bpm.model.bpmn.instance.di.Waypoint;
import org.camunda.bpm.model.xml.ModelInstance;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static com.pb.wkflow.core.camunda.bpmn.instance.VoteWork.*;


/**
 * camunda bpmn服务
 * @author 苗益辉
 * @date 2022/5/25 19:26
 */
@Service
public class WorkflowModelServiceImpl implements WorkflowModelService {

    /** 开始节点 */
    private static final String START_EVENT = "startEvent";
    /** 结束节点 */
    private static final String END_EVENT = "endEvent";
    /** 用户节点 */
    private static final String USER_TASK = "userTask";
    /** 服务节点 */
    private static final String SERVICE_TASK = "serviceTask";
    /** 连接线 */
    private static final String SEQUENCE_FLOW = "sequenceFlow";
    /** 排他网关 */
    private static final String EXCLUSIVE_GATEWAY = "exclusiveGateway";
    /** 包容网关 */
    private static final String INCLUSIVE_GATEWAY = "inclusiveGateway";
    /** 并行网关 */
    private static final String PARALLEL_GATEWAY = "parallelGateway";

    private static final String DEFAULT_PROPERTIES = "general";
    private static final String PROPERTIES = "properties";
    private static final String TRUE = "true";
    private static final String FALSE = "false";
    private static final String DOCUMENTATION = "documentation";
    private static final String OUTGOING = "outgoing";
    private static final String INCOMING = "incoming";

    private static final String DEFAULT_SERVICE_ONLINE_CLASS = "com.primb.core.service.IHttpServiceTaskService";

    /**
     * 创建空画布
     * @param modelInstance modelInstance
     */
    @Override
    public void createEmptyBpmnModel(BpmnModelInstance modelInstance) {
        Process process = modelInstance.getModelElementsByType(Process.class).iterator().next();
        StartEvent startEvent = modelInstance.newInstance(StartEvent.class);
        startEvent.setId("start");
        startEvent.setName("开始节点");
        process.addChildElement(startEvent);
    }


    /**
     * json 转 bpmn
     * @param modelInstance modelInstance
     * @param childShapes childShapes
     * @param processDefinition processDefinition
     */
    @Override
    public void createBpmnModel(BpmnModelInstance modelInstance, JSONArray childShapes,
                                ProcessDefinition processDefinition) {
        Process process = modelInstance.getModelElementsByType(Process.class).iterator().next();
        Map<String, FlowNode> flowNodes = new HashMap<>(2);
        Map<String, SequenceFlow> sequenceFlows = new HashMap<>(2);
        // 循环创建各种节点
        for(Object childShape : childShapes) {
            JSONObject shape = (JSONObject) childShape;
            String type = shape.getJSONObject(DEFAULT_PROPERTIES).getString("type");
            String id = shape.getJSONObject(DEFAULT_PROPERTIES).getString("id");
            String name = shape.getJSONObject(DEFAULT_PROPERTIES).getString("name");
            switch(type) {
                case START_EVENT:
                    buildStartEvent(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case END_EVENT:
                    buildEndEvent(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case USER_TASK:
                    buildUserTask(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case SERVICE_TASK:
                    buildServiceTask(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case PARALLEL_GATEWAY:
                    buildParallelGateway(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case EXCLUSIVE_GATEWAY:
                    buildExclusiveGateway(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case INCLUSIVE_GATEWAY:
                    buildInclusiveGateway(modelInstance, id, name, shape, process, flowNodes);
                    break;
                case SEQUENCE_FLOW:
                    buildSequenceFlow(modelInstance, id, name, shape, process, sequenceFlows);
                    break;
                default:
                    break;
            }
            if(!SEQUENCE_FLOW.equals(type)) {
                plainShape(modelInstance, shape, id, type);
            }
        }
        // 循环连接各个线
        for(Object childShape : childShapes) {
            JSONObject shape = (JSONObject) childShape;
            String type = shape.getJSONObject(DEFAULT_PROPERTIES).getString("type");
            String id = shape.getJSONObject(DEFAULT_PROPERTIES).getString("id");
            if(SEQUENCE_FLOW.equals(type)) {
                SequenceFlow sequenceFlow = sequenceFlows.get(id);
                String target = shape.getJSONObject(DEFAULT_PROPERTIES).getString("targetId");
                String source = shape.getJSONObject(DEFAULT_PROPERTIES).getString("sourceId");
                FlowNode targetNode = flowNodes.get(target);
                FlowNode sourceNode = flowNodes.get(source);
                sequenceFlow.setTarget(targetNode);
                sequenceFlow.setSource(sourceNode);
                process.addChildElement(sequenceFlow);
                targetNode.getIncoming().add(sequenceFlow);
                sourceNode.getOutgoing().add(sequenceFlow);
                String defaultFlow = shape.getJSONObject(PROPERTIES).getString("default");
                if(TRUE.equals(defaultFlow)) {
                    String gatewayType = shape.getJSONObject(DEFAULT_PROPERTIES).getString("sourceId");
                    if(gatewayType.contains(EXCLUSIVE_GATEWAY)) {
                        //排他网关
                        ExclusiveGateway exclusiveGateway = (ExclusiveGateway) flowNodes.get(gatewayType);
                        exclusiveGateway.setDefault(sequenceFlow);
                    }else if (gatewayType.contains(INCLUSIVE_GATEWAY)) {
                        //包容网关
                        InclusiveGateway inclusiveGateway = (InclusiveGateway) flowNodes.get(gatewayType);
                        inclusiveGateway.setDefault(sequenceFlow);
                    }
                }
            }
            if(SEQUENCE_FLOW.equals(type)) {
                plainShape(modelInstance, shape, id, type);
            }
        }
        // 判断流程图箭头是否错误
        Iterator<Process> iterator = modelInstance.getModelElementsByType(Process.class).iterator();
        while (iterator.hasNext()) {
            Iterator<FlowElement> flowElements = iterator.next().getFlowElements().iterator();
            while (flowElements.hasNext()) {
                FlowElement flow = flowElements.next();
                if (flow instanceof  StartEvent) {
                    // 开始节点不能有输入箭头，不能没有输出箭头
                    StartEvent startEvent = (StartEvent) flow;
                    if (CollectionUtils.isNotEmpty(startEvent.getIncoming())) {
                        throw new ApprovalException("开始节点不能有输入节点，发布失败");
                    }
                    if(CollectionUtils.isEmpty(startEvent.getOutgoing())) {
                        throw new ApprovalException("开始节点必须有输出节点，发布失败");
                    }
                } else if (flow instanceof EndEvent) {
                    // 结束节点不能有输出箭头，不能没有输入箭头
                    EndEvent endEvent = (EndEvent) flow;
                    if (CollectionUtils.isNotEmpty(endEvent.getOutgoing())) {
                        throw new ApprovalException("结束节点必须有输入节点，发布失败");
                    }
                    if(CollectionUtils.isEmpty(endEvent.getIncoming())) {
                        throw new ApprovalException("结束节点不能有输出节点，发布失败");
                    }
                } else if (flow instanceof Activity) {
                    // 活动节点需要输入和输出节点
                    Activity activity = (Activity) flow;
                    if (CollectionUtils.isEmpty(activity.getOutgoing())) {
                        throw new ApprovalException("活动节点必须有输入节点，发布失败");
                    }
                    if(CollectionUtils.isEmpty(activity.getIncoming())) {
                        throw new ApprovalException("活动节点必须有输出节点，发布失败");
                    }
                } else if (flow instanceof Gateway) {
                    // 网关需要输入和输出节点
                    Gateway gateway = (Gateway) flow;
                    if (CollectionUtils.isEmpty(gateway.getOutgoing())) {
                        throw new ApprovalException("网关必须有输入节点，发布失败");
                    }
                    if(CollectionUtils.isEmpty(gateway.getIncoming())) {
                        throw new ApprovalException("网关必须有输出节点，发布失败");
                    }
                }
            }
        }
        Definitions definitions = modelInstance.getDefinitions();
        definitions.setTargetNamespace(processDefinition.getCategory());
    }

    /**
     * 构建开始节点
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    private void buildStartEvent(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                     Process process,Map<String, FlowNode> flowNodes) {
        StartEvent startEvent = modelInstance.newInstance(StartEvent.class);
        String documentation = shape.getJSONObject(DEFAULT_PROPERTIES).getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, startEvent, id, name, documentation);
        process.addChildElement(startEvent);
        flowNodes.put(id, startEvent);
    }

    /**
     * 构建结束节点
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    private void buildEndEvent(ModelInstance modelInstance, String id, String name, JSONObject shape,
                               Process process,Map<String, FlowNode> flowNodes) {
        EndEvent endEvent = modelInstance.newInstance(EndEvent.class);
        String documentation = shape.getJSONObject(DEFAULT_PROPERTIES).getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, endEvent, id, name, documentation);
        process.addChildElement(endEvent);
        flowNodes.put(id, endEvent);
    }

    /**
     * 构建用户节点
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    private void buildUserTask(ModelInstance modelInstance, String id, String name, JSONObject shape,
                               Process process,Map<String, FlowNode> flowNodes) {
        UserTask userTask = modelInstance.newInstance(UserTask.class);
        String documentation = shape.getJSONObject(DEFAULT_PROPERTIES).getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, userTask, id, name, documentation);
        //扩展数据
        JSONObject properties = shape.getJSONObject(PROPERTIES);
        //创建扩展元素
        ExtensionElements extensionElements = modelInstance.newInstance(ExtensionElements.class);
        //参与者
        JSONObject userParticipantObject = properties.getJSONObject("userTaskParticipant");
        buildUserParticipant(modelInstance, extensionElements, userParticipantObject, id);
        //会签
        JSONObject voteWorkObject = properties.getJSONObject("voteWork");
        if(voteWorkObject != null) {
            //是否启用会签
            boolean enable = voteWorkObject.getBoolean("enable");
            if(enable) {
                buildLoopCharacteristics(modelInstance, userTask, extensionElements, voteWorkObject);
            }
        }
        userTask.addChildElement(extensionElements);
        process.addChildElement(userTask);
        flowNodes.put(id, userTask);
    }

    /**
     * 构建服务节点
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    private void buildServiceTask(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                  Process process,Map<String, FlowNode> flowNodes) {
        ServiceTask serviceTask = modelInstance.newInstance(ServiceTask.class);
        String documentation = shape.getJSONObject(DEFAULT_PROPERTIES).getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, serviceTask, id, name, documentation);
        //扩展数据
        JSONObject properties = shape.getJSONObject(PROPERTIES);
        if (properties == null) {
            throw new BizException("请配置服务节点");
        }
        String serviceType = properties.getString("serviceType");
        if(ExternalInterface.SERVICE_LOCAL.equals(serviceType)) {
            String serviceClass = properties.getString("serviceClass");
            serviceTask.setCamundaClass(serviceClass);
        }else if(ExternalInterface.SERVICE_ONLINE.equals(serviceType)) {
            serviceTask.setCamundaClass(DEFAULT_SERVICE_ONLINE_CLASS);
            //创建扩展元素
            ExtensionElements extensionElements = modelInstance.newInstance(ExtensionElements.class);
            ExternalInterface externalInterface = modelInstance.newInstance(ExternalInterface.class);
            String serviceUrl = properties.getString("serviceUrl");
            externalInterface.setTextContent(serviceUrl);
            extensionElements.addChildElement(externalInterface);
            serviceTask.addChildElement(extensionElements);
        }
        process.addChildElement(serviceTask);
        flowNodes.put(id, serviceTask);
    }

    /**
     * 构建并行网关，全部通过
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    public void buildParallelGateway(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                     Process process, Map<String, FlowNode> flowNodes) {
        ParallelGateway parallelGateway = modelInstance.newInstance(ParallelGateway.class);
        JSONObject properties = shape.getJSONObject(DEFAULT_PROPERTIES);
        String documentation = properties.getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, parallelGateway, id, name, documentation);
        process.addChildElement(parallelGateway);
        flowNodes.put(id, parallelGateway);
    }

    /**
     * 构建排他网关，按照箭头优先级只通过一个
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    public void buildExclusiveGateway(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                      Process process, Map<String, FlowNode> flowNodes) {
        ExclusiveGateway exclusiveGateway = modelInstance.newInstance(ExclusiveGateway.class);
        JSONObject properties = shape.getJSONObject(DEFAULT_PROPERTIES);
        String documentation = properties.getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, exclusiveGateway, id, name, documentation);
        process.addChildElement(exclusiveGateway);
        flowNodes.put(id, exclusiveGateway);
    }

    /**
     * 包容网关，条件满足则通过，条件不满足则跳过
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param flowNodes flowNodes
     */
    public void buildInclusiveGateway(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                      Process process, Map<String, FlowNode> flowNodes) {
        InclusiveGateway inclusiveGateway = modelInstance.newInstance(InclusiveGateway.class);
        JSONObject properties = shape.getJSONObject(DEFAULT_PROPERTIES);
        String documentation = properties.getString(DOCUMENTATION);
        buildBaseGeneral(modelInstance, inclusiveGateway, id, name, documentation);
        process.addChildElement(inclusiveGateway);
        flowNodes.put(id, inclusiveGateway);
    }

    /**
     * 构建箭头
     * @param modelInstance modelInstance
     * @param id id
     * @param name name
     * @param shape shape
     * @param process process
     * @param sequenceFlows sequenceFlows
     */
    public void buildSequenceFlow(ModelInstance modelInstance, String id, String name, JSONObject shape,
                                  Process process,Map<String, SequenceFlow> sequenceFlows) {
        SequenceFlow sequenceFlow = modelInstance.newInstance(SequenceFlow.class);
        sequenceFlow.setId(id);
        sequenceFlow.setName(name);
        //扩展数据
        JSONObject properties = shape.getJSONObject(PROPERTIES);
        String condition = properties.getString("condition");
        if(StringUtils.isNotBlank(condition)) {
            ConditionExpression conditionExpression = modelInstance.newInstance(ConditionExpression.class);
            conditionExpression.setTextContent(condition);
            sequenceFlow.setConditionExpression(conditionExpression);
        }
        ExtensionElements extensionElements = modelInstance.newInstance(ExtensionElements.class);
        //箭头优先级
        Priority priority = modelInstance.newInstance(Priority.class);
        Integer priorityNum = properties.getInteger("priority");
        if(priorityNum != null) {
            priority.setOrder(priorityNum);
        }else {
            priority.setOrder(0);
        }
        extensionElements.addChildElement(priority);
        sequenceFlow.addChildElement(extensionElements);
        sequenceFlows.put(id, sequenceFlow);
    }

    /**
     * 构建基础信息
     * @param modelInstance modelInstance
     * @param flowNode flowNode
     * @param id id
     * @param name name
     * @param description description
     */
    private void buildBaseGeneral(ModelInstance modelInstance, FlowNode flowNode, String id,
                                  String name, String description) {
        flowNode.setId(id);
        flowNode.setName(name);
        if(StringUtils.isNotBlank(description)) {
            Documentation documentation = modelInstance.newInstance(Documentation.class);
            documentation.setTextContent(description);
            flowNode.addChildElement(documentation);
        }
    }

    /**
     * 构建用户节点-参与者类型
     * @param modelInstance modelInstance
     * @param extensionElements extensionElements
     * @param userParticipantObject userParticipantObject
     * @param id id
     */
    public void buildUserParticipant(ModelInstance modelInstance, ExtensionElements extensionElements,
                                     JSONObject userParticipantObject, String id) {
        UserParticipant userParticipant = modelInstance.newInstance(UserParticipant.class);
        userParticipant.setParticipantType(userParticipantObject.getString("participantType"));
        userParticipant.setAboutData(userParticipantObject.getString("aboutData"));
        userParticipant.setServiceType(userParticipantObject.getString("serviceType"));
        userParticipant.setServiceBean(userParticipantObject.getString("serviceBean"));
        userParticipant.setServiceUrl(userParticipantObject.getString("serviceUrl"));
        userParticipant.setActivity(userParticipantObject.getString("activity"));
        //参与者类型
        String participantType = userParticipantObject.getString("participantType");
        if(StringUtils.isBlank(participantType)) {
            throw new ApprovalException("请配置人工节点的参与者，人工节点为：" + id);
        }
        //流程参与者
        if(UserParticipant.CONFIG_TYPE_1.equals(participantType)) {
            JSONArray participants = userParticipantObject.getJSONArray("participants");
            if(!participants.isEmpty()) {
                Iterator<Object> iterator = participants.iterator();
                while(iterator.hasNext()) {
                    JSONObject next = (JSONObject) iterator.next();
                    Participants participant = modelInstance.newInstance(Participants.class);
                    participant.setId(next.getString("id"));
                    participant.setType(next.getString("type"));
                    participant.setName(next.getString("name"));
                    userParticipant.addChildElement(participant);
                }
            }else {
                throw new ApprovalException("请配置人工节点的参与者，人工节点为：" + id);
            }
        } else if (UserParticipant.CONFIG_TYPE_3.equals(participantType)) {
          if (StringUtils.isBlank(userParticipant.getActivity())) {
              throw new ApprovalException("请配置人工节点的流程执行者，人工节点为：" + id);
          }
        } else if (UserParticipant.CONFIG_TYPE_4.equals(participantType)) {
            if (StringUtils.isBlank(userParticipant.getAboutData())) {
                throw new ApprovalException("请配置人工节点的流程变量，人工节点为：" + id);
            }
        } else if(UserParticipant.CONFIG_TYPE_5.equals(participantType)) {
            JSONArray ruleLogicParams = userParticipantObject.getJSONArray("ruleLogicParam");
            if(!ruleLogicParams.isEmpty()) {
                Iterator<Object> iterator = ruleLogicParams.iterator();
                while(iterator.hasNext()) {
                    JSONObject next = (JSONObject) iterator;
                    RuleLogicParam ruleLogicParam = modelInstance.newInstance(RuleLogicParam.class);
                    ruleLogicParam.setParam(next.getString("param"));
                    ruleLogicParam.setName(next.getString("name"));
                    ruleLogicParam.setType(next.getString("type"));
                    ruleLogicParam.setValue(next.getString("value"));
                    userParticipant.addChildElement(ruleLogicParam);
                }
            } else {
                throw new ApprovalException("请配置人工节点的外部服务，人工节点为：" + id);
            }
        }
        //参与者元素添加到扩展元素
        extensionElements.addChildElement(userParticipant);
    }

    /**
     * 会签策略
     * 全部同意、一票否决 ${ nrOfPassInstances == nrOfInstances }
     * 一票通过 ${ nrOfPassInstances >= 1 }
     * 半数通过 ${ nrOfPassInstances / nrOfInstances >= 0.5 }
     * 三分之二通过 ${ nrOfPassInstances / nrOfInstances >= 2/3 }
     * @param modelInstance modelInstance
     * @param userTask userTask
     * @param extensionElements extensionElements
     * @param voteWorkObject voteWorkObject
     */
    private void buildLoopCharacteristics(ModelInstance modelInstance, UserTask userTask, ExtensionElements extensionElements, JSONObject voteWorkObject) {
        VoteWork voteWork = modelInstance.newInstance(VoteWork.class);
        voteWork.setAllocation(voteWorkObject.getString("allocation"));
        voteWork.setIsSequential(voteWorkObject.getString("isSequential"));
        voteWork.setFinishRule(voteWorkObject.getString("finishRule"));
        voteWork.setPassNum(voteWorkObject.getString("passNum"));
        voteWork.setPassPercent(voteWorkObject.getString("passPercent"));
        //添加多工作项配置到扩展元素
        extensionElements.addChildElement(voteWork);
        //添加会签
        MultiInstanceLoopCharacteristics loopCharacteristics = modelInstance.newInstance(MultiInstanceLoopCharacteristics.class);
        //true 串行会签， false 并行会签
        loopCharacteristics.setSequential(TRUE.equals(voteWork.getIsSequential()));
        loopCharacteristics.setCamundaCollection("postInfoList");
        loopCharacteristics.setCamundaElementVariable("postInfo");
        String finishRule = voteWork.getFinishRule();
        String completeStr = "";
        if(FINISH_BY_ALL.equals(finishRule)) {
            //全部通过
            completeStr = "${nrOfPassInstances == nrOfInstances}";
        }else if (FINISH_BY_NUM.equals(finishRule)) {
            //同意人数
            completeStr = "${nrOfPassInstances >= "+voteWork.getPassNum()+"}";
        }else if (FINISH_BY_PERCENT.equals(finishRule)) {
            //同意百分比
            double d = new BigDecimal(voteWork.getPassPercent()).divide(new BigDecimal(100)).doubleValue();
            completeStr = "${nrOfPassInstances / nrOfInstances >= "+ d +"}";
        }
        if(StringUtils.isNotBlank(completeStr)) {
            CompletionCondition completionCondition = modelInstance.newInstance(CompletionCondition.class);
            completionCondition.setTextContent(completeStr);
            loopCharacteristics.addChildElement(completionCondition);
        }
        userTask.addChildElement(loopCharacteristics);
    }

    public void plainShape(BpmnModelInstance modelInstance, JSONObject shape, String id, String type) {
        Collection<BpmnDiagram> bpmnDiagrams = modelInstance.getDefinitions().getBpmDiagrams();
        BpmnDiagram diagram = bpmnDiagrams.iterator().next();
        BpmnPlane bpmnPlane = diagram.getBpmnPlane();
        BaseElement baseElement = modelInstance.getModelElementById(id);
        if(!SEQUENCE_FLOW.equals(type)) {
            BpmnShape bpmnShape = modelInstance.newInstance(BpmnShape.class);
            bpmnPlane.addChildElement(bpmnShape);
            JSONObject shapeObject = shape.getJSONObject("bounds");
            bpmnShape.setBpmnElement(baseElement);
            Bounds bounds = modelInstance.newInstance(Bounds.class);
            bounds.setX(shapeObject.getInteger("left"));
            bounds.setY(shapeObject.getInteger("top"));
            bounds.setWidth(shapeObject.getInteger("width"));
            bounds.setHeight(shapeObject.getInteger("height"));
            bpmnShape.addChildElement(bounds);
        }else {
            BpmnEdge bpmnEdge = modelInstance.newInstance(BpmnEdge.class);
            bpmnPlane.addChildElement(bpmnEdge);
            Integer sourceAnchor = null;
            Integer targetAnchor = null;
            sourceAnchor = shape.getInteger("sourceAnchor");
            targetAnchor = shape.getInteger("targetAnchor");
            bpmnEdge.setBpmnElement(baseElement);
            Waypoint waypoint1 = modelInstance.newInstance(Waypoint.class);
            if(sourceAnchor != null) {
                waypoint1.setX(sourceAnchor);
            } else {
                waypoint1.setX(-1);
            }
            if (targetAnchor != null) {
                waypoint1.setY(targetAnchor);
            } else {
                waypoint1.setY(-1);
            }
            bpmnEdge.addChildElement(waypoint1);
            Waypoint waypoint2 = modelInstance.newInstance(Waypoint.class);
            if(sourceAnchor != null) {
                waypoint2.setX(sourceAnchor);
            } else {
                waypoint2.setX(-1);
            }
            if (targetAnchor != null) {
                waypoint2.setY(targetAnchor);
            } else {
                waypoint2.setY(-1);
            }
            bpmnEdge.addChildElement(waypoint1);
            bpmnEdge.addChildElement(waypoint2);
        }
    }
}
